package lumis.portal.lock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * A simple mutual exclusive lock implementation.
 *
 * @version $Revision: 9601 $ $Date: 2008-07-18 15:38:17 -0300 (Fri, 18 Jul 2008) $
 * @since 4.2.0
 */
class Mutex implements Lock
{
	/**
	 * Internal helper class for lock acquisitions and synchronizations.
	 * Uses a state value of zero for unlocked state and a state value of one
	 * for locked state.
	 *
	 * @version $Revision: 9601 $ $Date: 2008-07-18 15:38:17 -0300 (Fri, 18 Jul 2008) $
	 * @since 4.2.0
	 */
	@SuppressWarnings("serial")
	private static class Sync extends AbstractQueuedSynchronizer
	{
		protected boolean isHeldExclusively()
		{
			return getState() == 1;
		}

		public boolean tryAcquire(int acquires)
		{
			return compareAndSetState(0, 1);
		}

		protected boolean tryRelease(int releases)
		{
			if (getState() == 0)
				throw new IllegalMonitorStateException();
			setState(0);
			return true;
		}

		Condition newCondition()
		{
			return new ConditionObject();
		}
	}

	private final Sync sync = new Sync();

	public void lock()
	{
		sync.acquire(1);
	}

	public boolean tryLock()
	{
		return sync.tryAcquire(1);
	}

	public void unlock()
	{
		sync.release(1);
	}

	public Condition newCondition()
	{
		return sync.newCondition();
	}

	public void lockInterruptibly() throws InterruptedException
	{
		sync.acquireInterruptibly(1);
	}

	public boolean tryLock(long timeout, TimeUnit unit)
			throws InterruptedException
	{
		return sync.tryAcquireNanos(1, unit.toNanos(timeout));
	}
}